Skip to main content

libobs_simple\sources\linux\sources/
linux_general_screen_capture.rs

1use libobs_wrapper::{
2    data::ObsObjectBuilder,
3    runtime::ObsRuntime,
4    sources::{ObsSourceBuilder, ObsSourceRef},
5    utils::{ObjectInfo, ObsError, ObsString, PlatformType},
6};
7
8use crate::sources::{
9    linux::{
10        pipewire::{ObsPipeWireSourceRef, PipeWireScreenCaptureSourceBuilder},
11        X11CaptureSourceBuilder,
12    },
13    ObsEither, ObsEitherSource,
14};
15
16pub struct LinuxGeneralScreenCaptureBuilder {
17    underlying_builder: ObsEither<X11CaptureSourceBuilder, PipeWireScreenCaptureSourceBuilder>,
18}
19
20impl ObsObjectBuilder for LinuxGeneralScreenCaptureBuilder {
21    fn new<T: Into<ObsString> + Send + Sync>(name: T, runtime: ObsRuntime) -> Result<Self, ObsError>
22    where
23        Self: Sized,
24    {
25        let platform = runtime.get_platform()?;
26        let underlying_builder = match platform {
27            PlatformType::X11 => ObsEither::Left(X11CaptureSourceBuilder::new(name, runtime)?),
28            PlatformType::Wayland => {
29                ObsEither::Right(PipeWireScreenCaptureSourceBuilder::new(name, runtime)?)
30            }
31            PlatformType::Invalid => {
32                return Err(ObsError::PlatformInitError(
33                    "No platform could be found to create the source on.".to_string(),
34                ))
35            }
36        };
37
38        Ok(Self { underlying_builder })
39    }
40
41    fn runtime(&self) -> &ObsRuntime {
42        match &self.underlying_builder {
43            ObsEither::Left(builder) => builder.runtime(),
44            ObsEither::Right(builder) => builder.runtime(),
45        }
46    }
47
48    fn get_name(&self) -> ObsString {
49        match &self.underlying_builder {
50            ObsEither::Left(builder) => builder.get_name(),
51            ObsEither::Right(builder) => builder.get_name(),
52        }
53    }
54
55    fn object_build(self) -> Result<ObjectInfo, ObsError>
56    where
57        Self: Sized,
58    {
59        match self.underlying_builder {
60            ObsEither::Left(builder) => builder.object_build(),
61            ObsEither::Right(builder) => builder.object_build(),
62        }
63    }
64
65    fn get_settings(&self) -> &libobs_wrapper::data::ObsData {
66        match &self.underlying_builder {
67            ObsEither::Left(builder) => builder.get_settings(),
68            ObsEither::Right(builder) => builder.get_settings(),
69        }
70    }
71
72    fn get_settings_updater(&mut self) -> &mut libobs_wrapper::data::ObsDataUpdater {
73        match &mut self.underlying_builder {
74            ObsEither::Left(builder) => builder.get_settings_updater(),
75            ObsEither::Right(builder) => builder.get_settings_updater(),
76        }
77    }
78
79    fn get_hotkeys(&self) -> &libobs_wrapper::data::ObsData {
80        match &self.underlying_builder {
81            ObsEither::Left(builder) => builder.get_hotkeys(),
82            ObsEither::Right(builder) => builder.get_hotkeys(),
83        }
84    }
85
86    fn get_hotkeys_updater(&mut self) -> &mut libobs_wrapper::data::ObsDataUpdater {
87        match &mut self.underlying_builder {
88            ObsEither::Left(builder) => builder.get_hotkeys_updater(),
89            ObsEither::Right(builder) => builder.get_hotkeys_updater(),
90        }
91    }
92
93    fn get_id() -> ObsString {
94        ObsString::from("linux_general_screen_capture")
95    }
96}
97
98pub type LinuxGeneralScreenCaptureSourceRef = ObsEitherSource<ObsSourceRef, ObsPipeWireSourceRef>;
99
100impl ObsSourceBuilder for LinuxGeneralScreenCaptureBuilder {
101    type T = LinuxGeneralScreenCaptureSourceRef;
102
103    fn build(self) -> Result<Self::T, ObsError>
104    where
105        Self: Sized,
106    {
107        match self.underlying_builder {
108            ObsEither::Left(builder) => {
109                let source = builder.build()?;
110                Ok(ObsEitherSource::Left(source))
111            }
112            ObsEither::Right(builder) => {
113                let source = builder.build()?;
114                Ok(ObsEitherSource::Right(source))
115            }
116        }
117    }
118}
119
120impl LinuxGeneralScreenCaptureBuilder {
121    /// Set the PipeWire restore token, which will be used to re-establish the same selection the
122    /// user did previously.
123    /// # Display Server
124    /// PipeWire only
125    pub fn set_restore_token(mut self, token: &str) -> Self {
126        self.underlying_builder = match self.underlying_builder {
127            ObsEither::Left(builder) => ObsEither::Left(builder),
128            ObsEither::Right(builder) => {
129                ObsEither::Right(builder.set_restore_token(token.to_string()))
130            }
131        };
132
133        self
134    }
135
136    /// # Display Server
137    /// All supported display servers
138    pub fn set_show_cursor(mut self, show: bool) -> Self {
139        self.underlying_builder = match self.underlying_builder {
140            ObsEither::Left(builder) => ObsEither::Left(builder.set_show_cursor(show)),
141            ObsEither::Right(builder) => ObsEither::Right(builder.set_show_cursor(show)),
142        };
143
144        self
145    }
146
147    /// Set the screen/display to capture
148    /// # Display Server
149    /// X11 only
150    pub fn set_screen(mut self, screen: i64) -> Self {
151        self.underlying_builder = match self.underlying_builder {
152            ObsEither::Left(builder) => ObsEither::Left(builder.set_screen(screen)),
153            ObsEither::Right(builder) => ObsEither::Right(builder),
154        };
155
156        self
157    }
158
159    /// Enable advanced settings for X11 capture
160    /// # Display Server
161    /// X11 only
162    pub fn set_advanced(mut self, advanced: bool) -> Self {
163        self.underlying_builder = match self.underlying_builder {
164            ObsEither::Left(builder) => ObsEither::Left(builder.set_advanced(advanced)),
165            ObsEither::Right(builder) => ObsEither::Right(builder),
166        };
167
168        self
169    }
170
171    /// Set the X server to connect to (when using advanced settings)
172    /// # Display Server
173    /// X11 only
174    pub fn set_server(mut self, server: &str) -> Self {
175        self.underlying_builder = match self.underlying_builder {
176            ObsEither::Left(builder) => ObsEither::Left(builder.set_server(server.to_string())),
177            ObsEither::Right(builder) => ObsEither::Right(builder),
178        };
179
180        self
181    }
182
183    /// Crop from top (in pixels)
184    /// # Display Server
185    /// X11 only
186    pub fn set_cut_top(mut self, cut_top: i64) -> Self {
187        self.underlying_builder = match self.underlying_builder {
188            ObsEither::Left(builder) => ObsEither::Left(builder.set_cut_top(cut_top)),
189            ObsEither::Right(builder) => ObsEither::Right(builder),
190        };
191
192        self
193    }
194
195    /// Crop from left (in pixels)
196    /// # Display Server
197    /// X11 only
198    pub fn set_cut_left(mut self, cut_left: i64) -> Self {
199        self.underlying_builder = match self.underlying_builder {
200            ObsEither::Left(builder) => ObsEither::Left(builder.set_cut_left(cut_left)),
201            ObsEither::Right(builder) => ObsEither::Right(builder),
202        };
203
204        self
205    }
206
207    /// Crop from right (in pixels)
208    /// # Display Server
209    /// X11 only
210    pub fn set_cut_right(mut self, cut_right: i64) -> Self {
211        self.underlying_builder = match self.underlying_builder {
212            ObsEither::Left(builder) => ObsEither::Left(builder.set_cut_right(cut_right)),
213            ObsEither::Right(builder) => ObsEither::Right(builder),
214        };
215
216        self
217    }
218
219    /// Crop from bottom (in pixels)
220    /// # Display Server
221    /// X11 only
222    pub fn set_cut_bot(mut self, cut_bot: i64) -> Self {
223        self.underlying_builder = match self.underlying_builder {
224            ObsEither::Left(builder) => ObsEither::Left(builder.set_cut_bot(cut_bot)),
225            ObsEither::Right(builder) => ObsEither::Right(builder),
226        };
227
228        self
229    }
230
231    pub fn capture_type_name(&self) -> PlatformType {
232        match &self.underlying_builder {
233            ObsEither::Left(_) => PlatformType::X11,
234            ObsEither::Right(_) => PlatformType::Wayland,
235        }
236    }
237}